"""
商品存储
使用嵌套字典或列表的字典存储商品信息，每个商品包含以下字段：
name（名称，字符串类型）
price（单价，浮点数类型）
stock（库存量，整数类型）

核心功能实现
通过函数封装以下操作：
商品查询：根据名称模糊匹配商品，返回所有符合条件的商品列表
库存校验：检查指定商品库存是否满足购买数量需求
价格计算：根据购买数量和单价计算总价，支持多种折扣规则
数据排序：按价格或库存量对商品进行升序/降序排列

语法要求
需综合运用以下Python特性：
逻辑判断：if-elif-else 多条件分支
循环结构：for 循环遍历容器

函数设计：
多返回值函数
默认参数值
可变位置参数（*args）
数据容器：列表、字典、集合的联合使用
匿名函数：使用lambda表达式实现排序规则
"""
# 商品库
goods = [
    {
        "name": "chips",
        "price": 6.5,
        "stock": 200
    }, {
        "name": "Instant noodles",
        "price": 5.0,
        "stock": 200
    }, {
        "name": "cigarette",
        "price": 12,
        "stock": 50
    }, {
        "name": "ham",
        "price": 5.0,
        "stock": 60
    },
]


# 商品查询函数
def search_goods(keyword, goods):
    """
    根据传入的商品名关键词，在商品库中查找匹配的商品信息。
    注意：由于lower()方法对中文无效，因此商品库中的商品名应为英文名称，且此函数一次只能查询一个商品的信息。
    如需查询多个商品或支持中文查询，可考虑使用更复杂的匹配逻辑或引入中文处理库。

    参数:
    keyword (str): 要查询的商品名关键词
    goods (list): 商品库，包含多个商品字典的列表，每个字典应包含'name'字段

    返回:
    list: 匹配的商品信息列表，每个元素为一个商品字典
    """
    search_result = []
    for x in goods:
        if keyword.lower() == x["name"].lower():
            search_result.append(x)
    return search_result

# 库存校验函数
def Inventory_verification(goods_name, num_need, goods):
    """
    校验指定商品的库存是否满足需求数量。
    此函数会遍历商品库，找到与传入商品名匹配的商品，并检查其库存是否足够。
    注意：此函数一次只能校验一个商品，且假设商品库中商品名是唯一的。
    如需校验多个商品或处理商品名重复的情况，需调整函数逻辑。

    参数:
    goods_name (str): 要校验的商品名
    num_need (int): 需求的商品数量
    goods (list): 商品库，包含多个商品字典的列表，每个字典应包含'name'和'stock'字段

    返回:
    tuple: 包含一个布尔值和一个列表。布尔值表示库存是否足够，列表存储对应商品的信息（如果找到）。
    """
    ver_result = []
    for i in goods:
        if i["name"].lower() == goods_name.lower():
            if i["stock"] >= num_need:
                ver_result.append(i)
                return True, ver_result
    # 如果遍历完商品库仍未找到匹配商品，可以返回False和空列表，或者根据需求调整

# 价格计算函数
def compute_goods(goods, *items):
    """
    计算购买多个商品的总价，并更新商品库存。
    此函数会遍历传入的商品列表，检查每个商品是否存在以及库存是否足够，
    然后计算总价并更新库存。对于库存不足的商品，会记录到未找到列表中。
    注意：此函数假设商品库中的商品名是唯一的，且每次调用会修改商品库的库存。
    如需更复杂的库存处理逻辑，可考虑将库存校验和价格计算分离为不同函数。

    参数:
    goods (list): 商品库，包含多个商品字典的列表，每个字典应包含'name', 'price', 和 'stock'字段
    *items: 可变数量的元组参数，每个元组包含要购买的商品名和数量，例如(商品名1, 数量1), (商品名2, 数量2), ...

    返回:
    tuple: 包含三个元素：总价（float）、未找到商品列表（list）、有效商品列表（list）。
            未找到商品列表和有效商品列表中的元素均为元组，包含商品名和数量。
    """
    pay_num = 0
    notfound_name = []
    found_name = []
    for name, num in items:
        found = False
        for x in goods:
            if x["name"].lower() == name.lower():
                found = True
                if x["stock"] >= num:
                    pay_num += x["price"] * num  # 累加总价
                    x["stock"] -= num  # 更新库存
                    found_name.append((name, num))
                else:
                    notfound_name.append((name, num))
                continue  # 跳过后续循环，因为已经找到匹配商品
        if not found:
            print(f"未找到商品{name}")
            notfound_name.append((name, num))  # 将未找到的商品添加到未找到列表
    return pay_num, notfound_name, found_name
    # return pay_num,*items在购买多个商品时，返回值会变成（总价, 商品1, 商品2...），导致解包数量不匹配


# 数据排序
# 数据排序：按价格或库存量对商品进行升序/降序排列
def Sorting_goods(goods, key="price", reverse=False):
    """
    对商品列表按指定字段进行排序

    参数:
    goods (list): 商品列表，每个元素为字典，包含至少'price'(价格)和'stock'(库存)字段
    key (str): 排序依据的字段，默认为"price"(价格)，可选"stock"(库存)
    reverse (bool): 排序顺序，False表示升序(默认)，True表示降序

    返回:
    list: 排序后的商品列表，保持字典结构不变

    示例:
    >>> goods = [
    ...     {'name': '商品A', 'price': 100, 'stock': 50},
    ...     {'name': '商品B', 'price': 80, 'stock': 30},
    ...     {'name': '商品C', 'price': 120, 'stock': 60}
    ... ]
    >>> sorted_by_price = Sorting_goods(goods)
    >>> print([item['name'] for item in sorted_by_price])
    ['商品B', '商品A', '商品C']  # 按价格升序排列

    >>> sorted_by_stock_desc = Sorting_goods(goods, key="stock", reverse=True)
    >>> print([item['name'] for item in sorted_by_stock_desc])
    ['商品C', '商品A', '商品B']  # 按库存降序排列
    """
    return sorted(goods, key=lambda x: x[key], reverse=reverse)
# 主界面

while True:
    print("""
    ____超市____
    商品清单请按“1”
    商品查询请按“2”
    库存校验请按“3”
    结算请按“4”
    退出请按“5”
    """)
    func_button = int(input("请输入："))
    # 数据排序
    if func_button == 1:
        sort_goods = Sorting_goods(goods,"stock",reverse=True)
        print(sort_goods)
     # 商品查询
    elif func_button == 2:
        keyword = input("请输入您想要查询的商品信息")
        goods_infor = search_goods(keyword, goods)
        for x in goods_infor:
            print(x)
    # 库存校验
    elif func_button == 3:
        goods_name = input("请输入您需要的商品名")
        num_need = int(input("请输入您需要的数量"))
        boolean_result, list_result = Inventory_verification(goods_name, num_need, goods)
        if boolean_result == True:
            print(f"库存足够，商品信息如下{list_result}")
        else:
            print("库存不足")
    #价格计算
    elif func_button == 4:
        item_list = []
        while True:
            goods_name_main = input("请输入您想要购买的商品(输入q结束)")
            if goods_name_main == "q":
                break
            num_need_main = int(input("请输入您想购买的数量"))
            # append方法只能添加一个元素，把商品名和数量添加为一个元组，再添加到列表内
            item_list.append((goods_name_main, num_need_main))
        if not item_list:
            print("没有选择商品")
            continue
        # 接收返回值

        """ 
              这种方式，如果在购买多个商品的情况下，返回的*item_list就不只两个元素，所以应该分开处理总价和商品列表
              且商品列表已经存在了
              total_price,goods_name_num=compute_goods(goods,*item_list)
              print(f"您想购买的商品是{goods_name_num},总价是{total_price}")
              """
        total_price, not_found, have_found = compute_goods(goods, *item_list)
        print("___购物清单___")
        for name, num in have_found:
            print(f"商品：{name} \t数量：{num}")
        print(f"总价{total_price}")

        if not_found:
            print("___不足清单___")
            for name, num in not_found:
                print(f"商品{name}，需要{num}件，库存不足")
    # 退出
    elif func_button == 5:
        print("欢迎下次使用")
        break
    else:
        print("请输入正确的按键")
